/*
 *  Author: VadRov
 *  Copyright (C) 2019, VadRov, all right reserved.
 *
 *  Драйвер для контроллера XPT2046 (HR2046 и т.п.)
 *
 *  Функции и возможности:
 *  - Опрос тачскрина (в прерывании и вне прерывания) с получением информации о координатах и длительности касания;
 *  - Определение статуса текущего касания тачскрина: нет касания, клик, удержание;
 * 	- Измерение температуры встроенным датчиком;
 * 	- Измерение напряжения батареи на входе VBAT контроллера (7 вывод м/с в корпусе TSSOP-16);
 * 	- Измерение напряжения на входе AUX контроллера (8 вывод м/с в корпусе TSSOP-16).
 * 	- Допускает работу на одном spi нескольких устройств.
 *
 *  Допускается свободное распространение без целей коммерческого использования.
 *  При коммерческом использовании необходимо согласование с автором.
 *  Распространятся по типу "как есть", то есть использование осуществляете на свой страх и риск.
 *  Автор не предоставляет никаких гарантий.
 *
 *  https://www.youtube.com/@VadRov
 *  https://dzen.ru/vadrov
 *  https://vk.com/vadrov
 *  https://t.me/vadrov_channel
 *
 */

#ifndef INC_XPT2046_H_
#define INC_XPT2046_H_



/*************************************** Настройки пользователя ***************************************/
/*
 * Количество повторов измерений напряжений, соответствующих координатам x и у точки касания тачскрина.
 * Этот параметр включает одно "холостое" измерение, неиспользуемое в расчете среднего (отбрасывается).
 * Рекомендуется не менее 9 повторов измерений (8 "полезных" + 1 "холостое")
 */
/*
 * 应力测量值的重复次数对应于x坐标和触点。
 * 此参数包括一个在平均值计算中未使用的“较差”测量值(被忽略)。
 * 建议至少重复测量 9 次(8 次“有用” + 1 次“坏”)
 */
#define XPT2046_TOUCH_REPEATED_MEASUREMENTS		4

/*
 * Длительность текущего касания тачскрина (в миллисекундах), при которой
 * такое касание будет распознаваться, как удержание
 */
/*
 * 当前触摸的持续时间(以毫秒为单位),其中
 * 这种接触将被认定为保留
 */
#define XPT2046_TOUCH_HOLD_TIME					1500

/*
 * Количество повторов измерений напряжений для определения других параметров (температура, напряжение на
 * входах VBAT и AUX).
 * Этот параметр включает одно "холостое" измерение, неиспользуемое в расчете среднего (отбрасывается).
 * Рекомендуется не менее 9 повторов измерений (8 "полезных" + 1 "холостое")
 */

/*
 * 用于确定其他参数的电压测量重复次数(温度,电压)
 * VBAT 和 AUX 输入。
 * 此参数包括一个在平均值计算中未使用的“较差”测量值(被忽略)。
 * 建议至少重复测量 9 次(8 次“有用” + 1 次“坏”)
 */
#define XPT2046_OTHER_REPEATED_MEASUREMENTS		4

/*
 * Опорное напряжение, мВ.
 * В контроллере XPT2046 есть внутренний источник опорного напряжения 2500 мВ (+/- 50 мВ).
 * Это напряжение может быть использовано АЦП при преобразовании.
 * Подключение внутреннего источника опорного напряжения определяет бит PD1 в управляющей команде.
 * Возможно подключение и использование (путем отключения внутреннего источника опорного напряжения
 * битом PD1 в управляющей команде) внешнего источника опорного напряжения (см. схему своей платы,
 * 9 вывод микросхемы в корпусе TSSOP-16).
 * В спецификации XPT2046 указано, что для обеспечения совместимости с контроллером тачскрина ADS7843
 * (не имеет внутреннего источника опорного напряжения) внутренее опорное напряжение XPT2046 должно
 * быть отключено при измерении напряжений на сенсоре (PD1 = 0).
 * В этом драйвере может быть использован, как внутренний, так и внешний источники опорного напряжения.
 */

 /*
  * 支撑电压,mV。
  * XPT2046 控制器具有 2500 mV (+/- 50 mV) 的内部基准电源。
  * 此电压可由ACP在转换时使用。
  * 内部支撑电压源的连接决定了控制单元中的PD1位。
  * 可连接和使用(通过关闭内部支撑电压源)
  * 控制单元中的 pd1 位) 外部支撑电压源(见你的收费计划,
  *  9 TSSOP-16 封装中的晶片输出。
  * XPT2046 规格表明,为了与 ADS7843 控制器兼容。
  * (无内部支撑电压源)内部支撑电压XPT2046应
  * 在传感器上测量电压时禁用(PD1 = 0)。
  * 此驱动器可以使用内部和外部基准电压源。
  */
#define XPT2046_INTERNAL_VREF //Используем внутренний источник опорного напряжения.
							  //Если используется внешний источник опорного напряжения,
							  //то строку закомментируйте.

#ifdef XPT2046_INTERNAL_VREF
#define XPT2046_VREF  2550 //Напряжение внутреннего источника опорного напряжения.
						   //Оно определено в спецификации на контроллер XPT2046 (2500 мВ +/- 50 мВ).
#else
#define XPT2046_VREF  2900 //Напряжение внешнего источника опорного напряжения.
						   //Измеряется на 9 выводе микросхемы XPT2046 в корпусе TSSOP-16.
						   //Здесь напряжение для моей платы. У вас может быть немного иным.
#endif
/*********************************** Конец настроек пользователя *************************************/


/* * * * * * * * * * * * * * * * * * * *
	BIT7  BIT6   BIT5  BIT4  BIT3  BIT2    BIT1  BIT0
	S     A2     A1    A0    MODE  SER/DFR PD1   PD0
* S - 起始位。控制命令是由1位S所确定的。
* A2 - A0 - ACP多路复用器通道选择位(连接到ACP的输入)。
* MODE - 转换位选择器(0-12位,1-8位)。
* SER/DFR是ACP输入类型选择位(0 - 差分,1 - 非对称)。
* 若要从计数器获取数据,应使用差分输入。
* 用于测量内部温度传感器的绝对电压值和
* VBAT和AUX输入应使用非对称ACP输入。
* PD1 - 打开和关闭内部支撑电压的位:
* 	0 - 关闭,使用外部支撑电压(连接到TSSOP-16封装中的9个XPT2046输出)
* 	1 - 启用,使用内部支撑电压(XPT2046 VREF电源内置2500mV +/- 50mV)。
* PD0 - 转换后关闭ACP的控制位(0 - 关闭,1 - 不关闭)。
* /

/************************** Команды контроллера XPT2046 для 8-битного spi ********************************/
// #define XPT2046_NOP 	0x00 //00000000 - "холостая" команда (стартовый бит S сброшен)
// #define XPT2046_INI		0x80 //10000000 - выключение АЦП и вн. опорного напряжения после преобразования
// 							 //для разрешения PENIRQ - т.н. "инициализация".
// #ifdef XPT2046_INTERNAL_VREF
// /* 12 битное преобразование, внутренний источник опорного напряжения, дифференциальный вход АЦП,
//  * АЦП не выключается после преобразования */
// #define XPT2046_Y 		0x93 //10010011 - измерение напряжения на сенсоре для координаты Y
// #define XPT2046_X 		0xD3 //11010011 - измерение напряжения на сенсоре для координаты X
// /* 12 битное преобразование, внутренний источник опорного напряжения, несимметричный вход АЦП,
//  * АЦП не выключается после преобразования */
// #define XPT2046_TEMP0 	0x87 //10000111 - первое измерение напряжения для определения температуры
// #define XPT2046_TEMP1 	0xF7 //11110111 - второе измерение напряжения (с увеличенным током)
// #define XPT2046_VBAT	0xA7 //10100111 - измерение напряжения на входе VBAT
// #define XPT2046_AUX		0xE7 //11100111 - измерение напряжения на входe AUX
// #else
// /* 12 битное преобразование, внешний источник опорного напряжения, дифференциальный вход АЦП,
//  * АЦП не выключается после преобразования */
// #define XPT2046_Y 		0x91 //10010001 - измерение напряжения на сенсоре для координаты Y
// #define XPT2046_X 		0xD1 //11010001 - измерение напряжения на сенсоре для координаты X
// /* 12 битное преобразование, внешний источник опорного напряжения, несимметричный вход АЦП,
//  * АЦП не выключается после преобразования */
// #define XPT2046_TEMP0 	0x85 //10000101 - первое измерение напряжения для определения температуры
// #define XPT2046_TEMP1 	0xF5 //11110101 - второе измерение напряжения (с увеличенным током)
// #define XPT2046_VBAT	0xA5 //10100101 - измерение напряжения на входе VBAT
// #define XPT2046_AUX		0xE5 //11100101 - измерение напряжения на входe AUX
// #endif



/*********** 用于 8 位 SPI 的 XPT2046 控制器命令 *****/
#define XPT2046_NOP 0x00 //00000000 - “冷”命令(引导位S被重置)
#define XPT2046_INI 0x80 //10000000 - 关闭ACP。转换后的支撑电压
// 用于解析 PENIRQ,即“初始化”。
#ifdef XPT2046_INTERNAL_VREF
/* 12 位转换,内部基准电压源,差动 ACP 输入,
* 转换后 ACP 不会关闭 */
#define XPT2046_Y 0x93 //10010011 - Y坐标传感器电压测量
#define XPT2046_X 0xD3 //11010011 - X 坐标传感器电压测量
/* 12 位转换,内部基准电压源,非对称 ACP 输入,
* 转换后 ACP 不会关闭 */
#define XPT2046_TEMP0 0x87 //10000111 - 用于温度测量的第一个电压测量
#define XPT2046_TEMP1 0xF7 //11110111 - 第二个电压测量(增加电流)
#define XPT2046_VBAT 0xA7 //10100111 - VBAT 输入电压测量
#define XPT2046_AUX 0xE7 //11100111 - 输入电压测量
#else
/* 12 位转换,外部基准电压源,差动 ACP 输入,
* 转换后 ACP 不会关闭 */
#define XPT2046_Y 0x91 //10010001 - Y坐标传感器电压测量
#define XPT2046_X 0xD1 //11010001 - X坐标传感器电压测量
/* 12 位转换,外部基准电压源,非对称ACP输入,
* 转换后 ACP 不会关闭 */
#define XPT2046_TEMP0 0x85 //10000101 - 用于温度测量的第一个电压测量
#define XPT2046_TEMP1 0xF5 //11110101 - 第二个电压测量(增加电流)
#define XPT2046_VBAT 0xA5 //10100101 - VBAT 输入电压测量
#define XPT2046_AUX 0xE5 //11100101 - 输入电压测量
#endif



/*********************************************************************************************************/

/* 塔奇斯克林的状态 */
typedef enum {
	XPT2046_STATUS_NOCLICK = 0,
	XPT2046_STATUS_CLICK,
	XPT2046_STATUS_HOLD
}XPT2046_status;

// /* XPT2046 连接数据 */
// typedef struct {
// SPI_TypeDef *spi;		//SPI
// uint8_t speed;  		// SPI 速度(从 0 - clk/2 到 7 - clk/256)
// GPIO_TypeDef *cs_port;	// 输出端口 T_CS
// uint16_t cs_pin;		//端口输出号c T_CS(配置为输出)
// GPIO_TypeDef *irq_port;	// 输出端口 T_IRQ
// uint16_t irq_pin;		// 带有 T_IRQ 的端口输出号(配置为具有 EXTI 中断分辨率的输入)
// IRQn_Type exti_irq;		// 输出 T_IRQ 的 EXTI 外部中断
// }XPT2046_ConnectionData;

/* 接触点坐标数据 */
typedef struct {
int x,y;
}tpoint;

/* 将触笔坐标转换为显示坐标的系数 */
typedef struct {
int64_t Dx1, Dx2, Dx3, Dy1, Dy2, Dy3, D
}tCoef;

/* 塔什干处理器 */
typedef struct {
// XPT2046_ConnectionData cnt_data;	// 连接数据 XPT2046
tpoint;					//最后一次触摸的坐标(在测距坐标中)
uint32_t last_click_time;	//最后一次触摸的持续时间,以系统计时器中断的次数表示
//从最后一次接触屏幕到释放屏幕
uint32_t click_time_counter;// 当前触摸持续时间计数器(也表示为系统计时器中断的次数)
uint8_t fl_interrupt;				// 允许在中断时更新计数器坐标的标志
uint8_t click;				// 一个标志,指示当前时刻是否有触摸
tCoef coef;							//将塔什干坐标转换为显示坐标的系数
uint8_t fl_timer;			// 允许或禁止处理器内部计时器计数的标志
uint32_t timer_counter;	//处理器内部计时器计数器
uint32_t timer_period;				// 处理器内部计时器计时器周期
uint8_t fl_wait_exti;		// 等待 EXTI 中断授权标志
XPT2046_status status;			// 塔什干民意调查状态: 没有点击,点击,保留
}XPT2046_Handler;
/* 带有语法处理程序的全局变量 */
extern XPT2046_Handler *touch;


/* EXTI 中断处理程序
(添加到相应的 EXTIx_IRQHandler 处理程序 - 请参阅。文件 stm32f4xx_it.c) */
void XPT2046_EXTICallback(XPT2046_Handler *t);
/* 系统计时器中断处理程序
(添加到 SysTick_Handler 处理程序 - 请参阅。文件 stm32f4xx_it.c) */
void XPT2046_TIMCallback(XPT2046_Handler *t);
/* 初始化速记处理程序 */
void XPT2046_InitTouch(XPT2046_Handler *t,uint32_t timer_update_period);
/* 塔奇斯克林民意调查 */
uint8_t XPT2046_GetTouch(XPT2046_Handler *t);
/* XPT2046 内置温度传感器的测量 */
int XPT2046_GetTemp(XPT2046_Handler *t);
/* AUX 输入电压测量(TSSOP-16 封装中的 8 个输出 m/s) */
int XPT2046_GetAux(XPT2046_Handler *t);
/* VBAT 输入端的电池电压测量(TSSOP-16 封装中的 7 输出 m/s) */
int XPT2046_GetVbat(XPT2046_Handler *t);











// /* Обработчик прерывания EXTI
//    (добавить в соответствующий обработчик EXTIx_IRQHandler - см. файл stm32f4xx_it.c) */
// void XPT2046_EXTICallback(XPT2046_Handler *t);

// /* Обработчик прерывания системного таймера
//    (добавить в обработчик SysTick_Handler - см. файл stm32f4xx_it.c) */
// void XPT2046_TIMCallback(XPT2046_Handler *t);

// /* Инициализация обработчика тачскрина */
// void XPT2046_InitTouch(XPT2046_Handler *t, uint32_t timer_update_period, XPT2046_ConnectionData *cnt_data);

// /* Опрос тачскрина */
// uint8_t XPT2046_GetTouch(XPT2046_Handler *t);

// /* Измерение температуры встроенным в XPT2046 датчиком */
// int XPT2046_GetTemp(XPT2046_Handler *t);

// /* Измерение напряжения на входе AUX (8 вывод м/с в корпусе TSSOP-16) */
// int XPT2046_GetAux(XPT2046_Handler *t);

// /* Измерение напряжения батареи на входе VBAT (7 вывод м/с в корпусе TSSOP-16) */
// int XPT2046_GetVbat(XPT2046_Handler *t);









#endif /* INC_XPT2046_H_ */
